package com.jn.exam.oss.controller;

import cn.hutool.core.convert.Convert;
import com.jn.exam.JwtUtils;
import com.jn.exam.R;
import com.jn.exam.oss.entity.FaceViolation;
import com.jn.exam.oss.entity.Student;
import com.jn.exam.oss.entity.vo.ImageBase64;
import com.jn.exam.oss.service.*;
import com.jn.exam.oss.utils.StrUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;

/**
 * @author 江南大学1033190417
 * @date 2022/1/10 0:22
 * <p>
 * 人脸识别后端接口
 */
@RestController
@RequestMapping("/examoss/faceaip")
@SuppressWarnings("all")
public class FaceController {

    @Autowired
    private FaceService faceService;

    @Autowired
    private OssService ossService;

    @Autowired
    private FaceViolationService faceViolationService;

    @Autowired
    private UcenterService ucenterService;


    //注册人脸
    @PostMapping("registerFace")
    public R registerFace(@RequestBody ImageBase64 image, HttpServletRequest request) throws IOException {
        StringBuffer imagebast64 = image.getImagebast64();
        //调用service层
        String userId = JwtUtils.getMemberIdByJwtToken(request);
        String faceGroupId = JwtUtils.getFaceGroupIdByJwtToken(request);
        Map<String, Object> registerFace = faceService.registerFace(imagebast64, userId, faceGroupId);
        if (registerFace == null || !((String) registerFace.get("error_msg")).equals("SUCCESS")) {
            return R.error().message("注册失败");
        }
        //更新数据库
        Student student = new Student();
        student.setId(userId);
        student.setIsRegisterFace(Boolean.TRUE);
        Boolean success = ucenterService.updateById(student).getSuccess();
        if (success) {
            return R.ok().message("注册成功");
        }
        return R.error().message("注册失败");
    }


    //人脸更新
    @PostMapping("updateFace")
    public R updateFace(@RequestBody ImageBase64 image, HttpServletRequest request) throws IOException {
        StringBuffer imagebast64 = image.getImagebast64();
        String id = JwtUtils.getMemberIdByJwtToken(request);
        String faceGroupId = JwtUtils.getFaceGroupIdByJwtToken(request);
        Map<String, Object> updateFace = faceService.updateFace(imagebast64, id, faceGroupId);
        if (Convert.toInt(updateFace.get("error_code")) != 0) {
            return R.error().message("更新失败");
        }
        return R.ok().message("更新成功");
    }

    //用于将用户从某个组中删除
    @PostMapping("deleteUserFromGroup/{faceGroupId}/{userId}")
    public R deleteUserFromGroup(@PathVariable("faceGroupId") String faceGroupId, @PathVariable("userId") String userId) throws Exception {
        Map<String, Object> map = faceService.deleteUserFromGroup(userId, faceGroupId);
        if (Convert.toInt(map.get("error_code")) != 0) {
            return R.error().message("删除失败");
        }
        return R.ok().message("删除成功");
    }

    //人脸检测


    /**
     * 返回状态码：1——未识别到人脸
     * 2——有多张人脸
     * 3——有一张人脸，但不是本人
     * 20000——符合
     */
    @ApiOperation("主要用于考试过程中")
    @PostMapping("faceCheck")
    public R faceCheck(@RequestBody ImageBase64 image, HttpServletRequest request, String examId) throws IOException {
        StringBuffer imagebast64 = image.getImagebast64();
        String studentId = JwtUtils.getMemberIdByJwtToken(request);
        String faceGroupId = JwtUtils.getFaceGroupIdByJwtToken(request);
        String base64 = imagebast64.substring(imagebast64.indexOf(",") + 1, imagebast64.length());
        Map<String, Object> faceCheck = faceService.faceCheck(base64);
        Integer code = Convert.toInt(faceCheck.get("error_code"));//返回的响应码
        if (code == null) {
            return R.error().message("服务器繁忙");
        }
        if (code == 222202) {//未检测到人脸的响应码
            saveFaceViolation(base64, examId, studentId, "未检测到人脸");
            return R.error().code(1).message("未识别到人脸");
        }
        if (code == 0) {//成功的响应码
            Integer faceNum = Convert.toInt(StrUtil.sub(Convert.toStr(faceCheck), "face_num=", ","));//人脸数
            if (faceNum > 1) {
                saveFaceViolation(base64, examId, studentId, "无关人员出现在摄像头中");
                return R.error().message("无关人员请离开").code(2);
            }
        }
        //现在只有一个人脸
        Map<String, Object> searchface = faceService.searchfaceOne(base64, studentId, faceGroupId);
        Double score = Convert.toDouble(StrUtil.sub(Convert.toStr(searchface), "score=", "}"));
        if (score != null && score >= 80) {
            return R.ok().message("符合规定");
        } else {
            //未找到该人脸，同步到数据库
            saveFaceViolation(base64, examId, studentId, "不是本人在考试");
            return R.error().message("请确认本人考试").code(3);
        }
    }

    @ApiOperation("主要用于平时人脸检测是否成功")
    @PostMapping("faceCheckNormal")
    public R faceCheckNormal(@RequestBody ImageBase64 image, HttpServletRequest request) throws IOException {
        StringBuffer imagebast64 = image.getImagebast64();
        String base64 = imagebast64.substring(imagebast64.indexOf(",") + 1, imagebast64.length());
        String userId = JwtUtils.getMemberIdByJwtToken(request);
        String faceGroupId = JwtUtils.getFaceGroupIdByJwtToken(request);
        Map<String, Object> searchface = faceService.searchfaceOne(base64, userId, faceGroupId);
        if (!(searchface == null) || ((String) searchface.get("error_msg")).equals("SUCCESS")) {
            //获取匹配得分
            String res = searchface.get("result").toString();
            String score = res.substring(res.lastIndexOf("=") + 1, res.lastIndexOf("."));
            Integer getScore = Integer.valueOf(score);
            if (getScore > 80) {
                return R.ok().message("认证成功");
            }
        }
        return R.error().message("认证失败");
    }

    private boolean saveFaceViolation(String base64, String examId, String studentId, String remark) {

        String url = ossService.uploadFaceImgBytes(base64);
        FaceViolation faceViolation = new FaceViolation();
        faceViolation.setExamId(examId).setStudentId(studentId).setRemark(remark).setFaceUrl(url);
        return faceViolationService.save(faceViolation);
    }

}
